package link

import (
	"bufio"
	"fmt"
	"math/rand"
	"os"
	"time"

	"github.com/molio/practice/ds/utils"
)

type CircularSingleLinkedList struct {
	Head *Node
}

func NewCircularSingleLinkedList() *CircularSingleLinkedList {
	return &CircularSingleLinkedList{Head: NewNode(0)}
}

func (csll *CircularSingleLinkedList) CreateCircularSingleLinkedList(isRandom bool, nlen int) {
	cNode := csll.Head
	if isRandom {
		rand.Seed(time.Now().Unix())
		for i := 0; i < nlen; i++ {
			node := NewNode(rand.Intn(100) + 1)
			cNode.Next = node
			node.Next = csll.Head
			cNode = cNode.Next
		}
	} else {
		var num int
		f := bufio.NewReader(os.Stdin)
		for {
			fmt.Println("请输入数字，回车继续，#结束")
			input, _ := f.ReadString('\n')
			if input == "#\n" {
				break
			}
			fmt.Sscan(input, &num)
			node := NewNode(num)
			cNode.Next = node
			node.Next = csll.Head
			cNode = cNode.Next
		}

	}
}

func (csll *CircularSingleLinkedList) TravelCircularSingleLinkedList() {
	cNode := csll.Head
	fmt.Printf("该节点为：head")
	for cNode.Next != csll.Head {
		if cNode.Data != 0 {
			fmt.Printf("->%v", cNode.Data)
		}
		cNode = cNode.Next
	}
	fmt.Printf("->%v\n", cNode.Data)
}

func (csll *CircularSingleLinkedList) InsertElementInTail(isRandom int, num int) {
	switch isRandom {
	case 1:
		rand.Seed(time.Now().Unix())
		num = rand.Intn(100) + 1
	case 2:
		num = utils.ReadInput()
	}
	fmt.Printf("尾插法,插入元素：%v\n", num)
	node := NewNode(num)
	cNode := csll.Head
	for cNode.Next != csll.Head {
		cNode = cNode.Next
	}
	cNode.Next = node
	node.Next = csll.Head
}

func (csll *CircularSingleLinkedList) InsertElementInHead(isRandom int, num int) {
	switch isRandom {
	case 1:
		rand.Seed(time.Now().Unix())
		num = rand.Intn(100) + 1
	case 2:
		num = utils.ReadInput()
	}
	fmt.Printf("头插法,插入元素：%v\n", num)
	node := NewNode(num)
	cNode := csll.Head
	node.Next = cNode.Next
	cNode.Next = node
}

func (csll *CircularSingleLinkedList) IsEmpty() bool {
	return csll.Head.Next == nil
}

func (csll *CircularSingleLinkedList) GetLength() int {
	if csll.IsEmpty() {
		return 0
	}
	cNode := csll.Head
	nlen := 0
	for cNode.Next != csll.Head {
		nlen += 1
		cNode = cNode.Next
	}
	return nlen
}

func (csll *CircularSingleLinkedList) FindElemnentByPos(pos int) *Node {
	cNode := csll.Head.Next
	ppos := 1
	for cNode != csll.Head {
		if ppos == pos {
			return cNode
		}
		ppos += 1
		cNode = cNode.Next
	}
	return nil
}

func (csll *CircularSingleLinkedList) FindElemnentPreNode(num int) *Node {
	cNode := csll.Head
	var preNode *Node
	for cNode.Data != num && cNode.Next != csll.Head { // 需要增加对最后结点的边界删除判断
		preNode = cNode
		cNode = cNode.Next
	}
	return preNode
}

func (csll *CircularSingleLinkedList) DeleteElement(num int) {
	fmt.Println("待删除的结点的值：", num)
	preNode := csll.FindElemnentPreNode(num)
	preNode.Next = preNode.Next.Next
}
